
from D_Individual import *
import F_Population
import numpy as np
from matplotlib import pyplot as plt, axes, font_manager
import matplotlib
import random
Zh_Font = matplotlib.font_manager.FontProperties(fname="../venv/include/SourceHanSansSC-Bold.otf")
plt.rc('font', family='Times New Roman')
plt.rc('font', size=25)
plt.rc('font', weight='bold')
legend_font = {
    'fname': 'C:/Windows/fonts/simhei.ttf',  # 引用系统字体
    'style': 'normal',
    'size': 25,  # 字号
    'weight': "normal",  # 是否加粗，不加粗
}

def Draw_Gatt_Me_Points_2d_sort(x, y, Nodominate_Ship):
    Nodominate_Ship_sort = []
    print(x)
    print(y)
    for i in range(len(Nodominate_Ship)):
        a = Nodominate_Ship[i]
        for j in range(len(a)):
            for k in range(j+1,len(a)):
                if(x[a[j]] > x[a[k]]):
                    t = a[j]
                    a[j] = a[k]
                    a[k] = t
        Nodominate_Ship_sort.append(a)
        # print(Nodominate_Ship_sort)


    plt.figure(figsize=(20, 10))

    # plt.xticks(np.arange(0, max(x) + 5, 10), fontsize=25, fontproperties=Zh_Font)
    # plt.yticks(np.arange(0, max(y) + 5, 10), fontsize=25, fontproperties=Zh_Font)
    plt.xticks(np.arange(0, 101, 10), fontsize=25, fontproperties=Zh_Font)
    plt.yticks(np.arange(0, 101, 10), fontsize=25, fontproperties=Zh_Font)
    plt.title("二维时间散点图", fontsize=40, fontproperties=Zh_Font)
    plt.ylabel('关键生产线负载', fontsize=30, fontproperties=Zh_Font)
    plt.xlabel('最短完工时间', fontsize=30, fontproperties=Zh_Font)
    Color = ['pink', 'tan', 'red', 'black','darkgreen', 'royalblue', 'lightcoral']
    Size  = [120, 120, 120, 120]
    color = ['pink']*len(x)
    size = [100]*len(x)
    print(color)
    for i in range(len(Nodominate_Ship)):  # 同一组的个体
        for j in range(len(Nodominate_Ship[i])):
            index = Nodominate_Ship_sort[i][j]
            color[index] = Color[i % len(Color)]
            size[index] = Size[i % len(Size)]
            if(j < len(Nodominate_Ship_sort[i])-1):
                # plt.plot(点坐标，点坐标，颜色)
                plt.plot([x[Nodominate_Ship_sort[i][j]],x[Nodominate_Ship_sort[i][j+1]]], [y[Nodominate_Ship_sort[i][j]],y[Nodominate_Ship_sort[i][j+1]]], color[index])
    print(color)
    # for a, b in zip(x, y):  # 添加这个循环显示坐标
    #     # plt.text（x值，y值，（坐标格式），位置，位置，大小）bottom
    #     plt.text(a, b, (a,b), ha='center', va='bottom', fontsize=13)
    plt.scatter(x, y, c=color, s=size)
    plt.show()

def Random_Initial_Population():
    Pop = F_Population.Population()
    for _ in range(100):
        Idv = Individual()
        x = random.randint(40, 100)
        y = random.randint(30, 100)
        Idv.Adaptability = [x, y]
        Pop.Population_Member.append(Idv)
    return Pop

# 判断个体1是否支配个体2
def Is_Dominate(Idv1, Idv2):
    # 目标空间维度

    # Objective_Dim = len(Idv1.Adaptability)
    Objective_Dim = 2
    # 两个个体的目标值
    Objective1 = []
    Objective2 = []

    for i in range(Objective_Dim):
        # Objective1.append(Idv1.Adaptability[i])
        # Objective2.append(Idv2.Adaptability[i])
        Objective1.append(Idv1.get_Adaptability_value(i))
        Objective2.append(Idv2.get_Adaptability_value(i))

    # 判断向量
    Flag = [9999] * Objective_Dim

    for i in range(Objective_Dim):
        if Objective1[i] < Objective2[i]:
            Flag[i] = -1    # 目标值小
        elif Objective1[i] == Objective2[i]:
            Flag[i] = 0     # 目标值相等

    # 判断支配的条件如下:
    # 不能全部相等 ---> 不能全0
    # 不能存在个体2目标值比个体1好的   ---> 不能有9999
    return True if sum(Flag) < 0  else False

# 计算Pareto前沿面 服务于快速非支配排序
# 输入：个体集合
# 输出：Pareto前沿面
def Get_First_Dominate(Population_Pub):
    Pop_Size = len(Population_Pub)       # 个体集合的数量
    Np = [0] * Pop_Size                  # 支配当前个体的 个体数量  初始化为0
    Sp = [[] for _ in range(Pop_Size)]   # 被当前个体支配的 个体集  初始化为[]
    First_Pareto = []                    # Pareto 前沿面
    for i in range(Pop_Size):
        for j in range(i+1,Pop_Size):
                # print(Population_Pub[i],Population_Pub[j])
                if Is_Dominate(Population_Pub[i], Population_Pub[j]):    # 个体i支配个体j
                    Np[j] += 1       # 支配个体j的个体数量加1
                    Sp[i].append(j)  # 将个体j加入个体i的支配集
                elif Is_Dominate(Population_Pub[j], Population_Pub[i]):  # 个体j支配个体i
                    Np[i] += 1       # 支配个体i的个体数量加1
                    Sp[j].append(i)  # 将个体i加入个体j的支配集
        # 如果没有个体支配个体i，则此个体是Parato解
        if Np[i] == 0:
            First_Pareto.append(i)
    print("Pop_Size:", Pop_Size)
    print("Np:", Np)
    print("Sp:", Sp)
    print("First_Pareto", First_Pareto)
    return Np,Sp,First_Pareto

# 快速非支配排序
# 输入：个体集合  并非整个种群
# 输出：非支配排序结果
def Fast_Nodominate_Sort(Population_Member):
    # 第一个Parato前沿面
    Np,Sp,First_Parato = Get_First_Dominate(Population_Member)
    Nodominate_Sort = []                      # 非支配排序每个等级

    while(len(First_Parato) != 0):
        Nodominate_Sort.append(First_Parato)  # 加入第一个前沿面
        Temp = []                             # 加入后续Pareto面
        for j in First_Parato:
            p = Sp[j]                         # 找到pareto前沿面个体的支配集
            for q in p:                       # 将支配集中每个个体都得 支配数减少1
                Np[q] -= 1
                if Np[q] == 0:                # 找到下一层前沿面  当前前沿面个体遍历完成 进行下一层
                    Temp.append(q)
        First_Parato = Temp
    print("Nodominate_Sort", Nodominate_Sort)
    print(len(Nodominate_Sort))
    return Nodominate_Sort


# 单个个体的测试，包括画图，可以在这个地方测试
if __name__ == "__main__":
    Pop = Random_Initial_Population()
    x = []
    y = []
    for idv in Pop.Population_Member:
        x.append(idv.Adaptability[0])
        y.append(idv.Adaptability[1])
    Nodominate_Sort = Fast_Nodominate_Sort(Pop.Population_Member)

    Draw_Gatt_Me_Points_2d_sort(x,y,Nodominate_Sort)